home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / Perl_WWW_Utilities / weblog1.1 / uncgi / uncgi.sh < prev   
Encoding:
Linux/UNIX/POSIX Shell Script  |  1995-04-05  |  18.9 KB  |  715 lines

  1. #! /bin/sh
  2. # This is a shell archive.  Remove anything before this line, then unpack
  3. # it by saving it into a file and typing "sh file".  To overwrite existing
  4. # files, type "sh file -c".  You can also feed this as standard input via
  5. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  6. # will see the following message at the end:
  7. #        "End of shell archive."
  8. # Contents:  README patchlevel.h Makefile uncgi.c
  9. # Wrapped by koreth@gerbilmeister on Wed Oct 19 00:50:17 1994
  10. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  11. if test -f 'README' -a "${1}" != "-c" ; then 
  12.   echo shar: Will not clobber existing file \"'README'\"
  13. else
  14. echo shar: Extracting \"'README'\" \(7639 characters\)
  15. sed "s/^X//" >'README' <<'END_OF_FILE'
  16. X
  17. X                             UN-CGI VERSION 1.2
  18. X                                       
  19. XContents
  20. X
  21. X     * Introduction
  22. X     * Installation
  23. X     * Usage
  24. X     * Other Features
  25. X     * Bugs
  26. X     * Frequently Asked Questions
  27. X       
  28. XIntroduction
  29. X
  30. X   
  31. X   
  32. X   This is uncgi 1.1, a frontend for processing queries and forms from
  33. X   the Web on UNIX systems. You can get it via anonymous ftp from
  34. X   ftp.hyperion.com or, depending on your browser, by following this
  35. X   link.
  36. X   
  37. X   Without this program, if you wanted to process a form, you'd have to
  38. X   either write or dig up routines to translate the values of the form's
  39. X   fields from "URL encoding" to whatever your program required. This was
  40. X   a hassle in C, and a real pain in the shell, and you had do things
  41. X   differently for GET and POST queries.
  42. X   
  43. X   Which is where uncgi comes in. It decodes all the form fields and
  44. X   sticks them into environment variables for easy perusal by a shell
  45. X   script, a C program, a Perl script, or whatever you like, then
  46. X   executes whatever other program you specify.
  47. X   
  48. X   (Actually, "uncgi" is something of a misnomer, as the weird URL syntax
  49. X   is from the HTML forms specification, not from CGI itself.)
  50. X   
  51. XInstallation
  52. X
  53. X   
  54. X   
  55. X   To install, edit the Makefile, setting "CGI_BIN" to point to your HTTP
  56. X   server's CGI directory. Under NCSA httpd, this is usually a directory
  57. X   called "cgi-bin" in the server root directory. Then run "make
  58. X   install".
  59. X   
  60. X   Note that the variable serves two purposes as supplied: it tells the
  61. X   Makefile where to install uncgi, and it also tells uncgi where to look
  62. X   for backend scripts. If you would like uncgi to look in a directory
  63. X   other than the one it's installed in, set DESTDIR to the install
  64. X   directory and CGI_BIN to the directory containing the scripts and
  65. X   programs that uncgi will be executing.
  66. X   
  67. XUsage
  68. X
  69. X   
  70. X   
  71. X   An example is the easiest way to demonstrate uncgi's use. Suppose you
  72. X   have the following in an HTML file:
  73. X
  74. X<form method=POST action="/cgi-bin/uncgi/myscript/thanks.html">
  75. XWhat's your name?
  76. X<input type=text size=30 name=name>
  77. X<p>
  78. XType some comments.
  79. X<br>
  80. X<textarea name=comments rows=10 cols=60></textarea>
  81. XWhat problem are you having? <select name=problem multiple>
  82. X<option> Can't sleep
  83. X<option> Unruly goat
  84. X<option> Limousine overcrowding
  85. X</select>
  86. X<p>
  87. X<input type=submit value="  Send 'em in!  ">
  88. X</form>
  89. X
  90. X   When the user selects the "Send 'em in!" button, the HTTP server will
  91. X   run uncgi. Uncgi will set three environment variables, WWW_name,
  92. X   WWW_comments and WWW_problem, to the values of the "name", "comments",
  93. X   and "problem" fields in the form, respectively. Then it will execute
  94. X   myscript in the CGI_BIN directory. If more than one "problem" is
  95. X   selected, the values will all be placed in WWW_comments, separated by
  96. X   hash marks ('#').
  97. X   
  98. X   All the usual CGI environment variables (PATH_INFO, QUERY_STRING,
  99. X   etc.) are available to the script or program you tell uncgi to run. A
  100. X   couple of them (PATH_INFO and PATH_TRANSLATED) are tweaked by uncgi to
  101. X   the values they'd have if your program were being executed directly by
  102. X   the server. In the above example, when uncgi ran myscript, PATH_INFO
  103. X   would be set to "/thanks.html". This is an easy way to specify
  104. X   additional parameters to your script without resorting to hidden
  105. X   fields.
  106. X   
  107. X   Myscript might be as simple as this:
  108. X
  109. X#!/bin/sh
  110. Xecho 'Content-type: text/html'
  111. Xecho ''
  112. Xmail webmaster << __EOF__
  113. X$WWW_name said:
  114. X$WWW_comments
  115. X__EOF__
  116. Xcat $PATH_TRANSLATED
  117. X
  118. X   With uncgi, that's all you need to do to write a script to send you
  119. X   mail from a form and print a prewritten file as a response. And it's
  120. X   the same whether you want to use GET or POST queries.
  121. X   
  122. XOther Features
  123. X
  124. X   
  125. X   
  126. X   Extra feature: If you compile with -DNO_MAIN, you can use uncgi as a
  127. X   library function in a C program of your own. Just call uncgi() at the
  128. X   start of your program.
  129. X   
  130. X   Uncgi will handle hybrid GET/POST requests. Specify a method of POST
  131. X   in the form, and add a GET-style query string to the action, for
  132. X   example <form method=POST
  133. X   action="/cgi-bin/uncgi/myscript?form_id=feedback">. When your script
  134. X   is run, WWW_form_id will be set to "feedback". This will only work if
  135. X   your HTTP server supports it (NCSA's does, for now anyway.)
  136. X   
  137. XBugs
  138. X
  139. X   
  140. X   
  141. X   There should be a way to specify a list of directories that uncgi will
  142. X   search for backend scripts.
  143. X   
  144. XFrequently Asked Questions
  145. X
  146. X  WHERE DO I PUT EVERYTHING?
  147. X  
  148. X   
  149. X   
  150. X   Short answer: Your server's cgi-bin directory.
  151. X   
  152. X   Long answer: When you edit uncgi's Makefile, you'll see two macro
  153. X   definitions. The first, CGI_BIN, tells uncgi where to look for your
  154. X   scripts or programs. It must be set to the name of an existing
  155. X   directory; you can set it to any directory you like. Usually it's set
  156. X   to the location of your server's cgi-bin directory.
  157. X   
  158. X   The second, DESTDIR, tells the Makefile where to install uncgi. By
  159. X   default, it's set to the same thing CGI_BIN is. It must point to your
  160. X   server's cgi-bin directory, so you'll need to change it if you set
  161. X   CGI_BIN to something else.
  162. X   
  163. X  WHY DOES UNCGI TELL ME IT CAN'T RUN MY SCRIPT?
  164. X  
  165. X   
  166. X   
  167. X   First, make sure your script is in the right place; see the preceding
  168. X   section.
  169. X   
  170. X   Second, make sure your script can be executed by the server. Remember,
  171. X   the server probably isn't running from your account, so you need to
  172. X   set the permissions on your script such that it can be run by any
  173. X   user. Usually, you can say "chmod 755 scriptname" (replacing
  174. X   scriptname with the name of your script) to set the permissions
  175. X   properly.
  176. X   
  177. X  WHAT DO I DO IN MY FORMS?
  178. X  
  179. X   
  180. X   
  181. X   The <form> tag has two attributes, METHOD and ACTION. METHOD must be
  182. X   set to either GET or POST; uncgi will handle either one, but POST is
  183. X   preferred if you have textarea fields or are expecting a lot of
  184. X   information from the client. Note that the attribute name (METHOD) can
  185. X   be upper or lower case, but the value must be all caps.
  186. X   
  187. X   ACTION should have the following components:
  188. X     * The alias for your server's cgi-bin directory (usually just
  189. X       /cgi-bin/)
  190. X     * uncgi/ to tell the server which program to execute.
  191. X     * The name of your script as it appears in the directory where you
  192. X       told uncgi to find your scripts and programs (the CGI_BIN macro in
  193. X       the Makefile.) Example: myscript
  194. X     * Optionally, a forward slash followed by additional parameters,
  195. X       often the path to another file you want your script to print. This
  196. X       path information will be available to your script in the PATH_INFO
  197. X       and PATH_TRANSLATED environment variables (the latter contains the
  198. X       full path to the document, including the path to the server root
  199. X       directory.) Note that you can't use tilde notation. Example:
  200. X       /form_output/acknowledge.html
  201. X       
  202. X   
  203. X   
  204. X   So, if you wanted to tell uncgi to run sendmemail with no additional
  205. X   parameters, you'd put sendmemail in the directory you specified as the
  206. X   value of CGI_BIN in uncgi's makefile, and use the following tag to
  207. X   begin your form:
  208. X   
  209. X     <form method=POST action="/cgi-bin/uncgi/sendmemail">
  210. X     
  211. X  I GET AN ERROR CODE 500 FROM THE SERVER.
  212. X  
  213. X   
  214. X   
  215. X   This usually means your script isn't specifying a content type to the
  216. X   server. The first thing your script needs to output is:
  217. X   
  218. X     Content-type: text/html
  219. X     
  220. X   followed by a blank line.
  221. X     _________________________________________________________________
  222. X   
  223. X      Maintained by Steven Grimm <koreth@hyperion.com>.
  224. X      Send mail if you have comments or suggestions.
  225. END_OF_FILE
  226. if test 7639 -ne `wc -c <'README'`; then
  227.     echo shar: \"'README'\" unpacked with wrong size!
  228. fi
  229. # end of 'README'
  230. fi
  231. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  232.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  233. else
  234. echo shar: Extracting \"'patchlevel.h'\" \(22 characters\)
  235. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  236. X#define VERSION "1.2"
  237. END_OF_FILE
  238. if test 22 -ne `wc -c <'patchlevel.h'`; then
  239.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  240. fi
  241. # end of 'patchlevel.h'
  242. fi
  243. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  244.   echo shar: Will not clobber existing file \"'Makefile'\"
  245. else
  246. echo shar: Extracting \"'Makefile'\" \(521 characters\)
  247. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  248. X#
  249. X# @(#)Makefile    1.2 8/21/94
  250. X#
  251. X# Makefile for "uncgi"
  252. X#
  253. X
  254. X#
  255. X# Set this to the directory where your CGI scripts live.  Uncgi will look
  256. X# there for backend scripts.
  257. X#
  258. XCGI_BIN = /home/gerbilmeister/www/cgi-bin
  259. X
  260. X#
  261. X# Set this to the directory you'd like to install uncgi in, if different
  262. X# from CGI_BIN.
  263. X#
  264. XDESTDIR = $(CGI_BIN)
  265. X
  266. Xuncgi: uncgi.c
  267. X    $(CC) $(CFLAGS) -DCGI_BIN='"$(CGI_BIN)"' -o $@ uncgi.c
  268. X
  269. Xinstall: uncgi
  270. X    cp uncgi $(DESTDIR)
  271. X    chmod 755 $(DESTDIR)/uncgi
  272. X
  273. Xshar:
  274. X    shar README patchlevel.h Makefile uncgi.c > uncgi.shar
  275. END_OF_FILE
  276. if test 521 -ne `wc -c <'Makefile'`; then
  277.     echo shar: \"'Makefile'\" unpacked with wrong size!
  278. fi
  279. # end of 'Makefile'
  280. fi
  281. if test -f 'uncgi.c' -a "${1}" != "-c" ; then 
  282.   echo shar: Will not clobber existing file \"'uncgi.c'\"
  283. else
  284. echo shar: Extracting \"'uncgi.c'\" \(8558 characters\)
  285. sed "s/^X//" >'uncgi.c' <<'END_OF_FILE'
  286. X/*
  287. X * @(#)uncgi.c    1.7 10/19/94
  288. X *
  289. X * Unescape all the fields in a form and stick them in the environment
  290. X * so they can be used without awful machinations.
  291. X *
  292. X * Call with an ACTION such as:
  293. X *    http://foo.bar.com/cgi-bin/uncgi/myscript/extra/path/stuff
  294. X *
  295. X * Uncgi will run "myscript" from the cgi-bin directory, and set PATH_INFO
  296. X * to "/extra/path/stuff".
  297. X *
  298. X * Environment variable names are "WWW_" plus the field name.
  299. X *
  300. X * Copyright 1994, Steven Grimm <koreth@hyperion.com>.
  301. X *
  302. X * Permission is granted to redistribute freely and use for any purpose,
  303. X * commercial or private, so long as this copyright notice is retained
  304. X * and the source code is included free of charge with any binary
  305. X * distributions.
  306. X */
  307. X#include <stdio.h>
  308. X#include <ctype.h>
  309. X
  310. Xvoid *malloc(), *realloc();
  311. Xchar *getenv();
  312. X
  313. Xextern char *sys_errlist[];
  314. Xextern int errno;
  315. X
  316. X#define PREFIX    "WWW_"
  317. X#define ishex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || \
  318. X          ((x) >= 'A' && (x) <= 'F'))
  319. X
  320. X/*
  321. X * Convert two hex digits to a value.
  322. X */
  323. Xstatic int
  324. Xhtoi(s)
  325. X    unsigned char    *s;
  326. X{
  327. X    int    value;
  328. X    char    c;
  329. X
  330. X    c = s[0];
  331. X    if (isupper(c))
  332. X        c = tolower(c);
  333. X    value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
  334. X
  335. X    c = s[1];
  336. X    if (isupper(c))
  337. X        c = tolower(c);
  338. X    value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
  339. X
  340. X    return (value);
  341. X}
  342. X
  343. X/*
  344. X * Get rid of all the URL escaping in a string.  Modify it in place, since
  345. X * the result will always be equal in length or smaller.
  346. X */
  347. Xstatic void
  348. Xurl_unescape(str)
  349. X    unsigned char    *str;
  350. X{
  351. X    unsigned char    *dest = str;
  352. X
  353. X    while (str[0])
  354. X    {
  355. X        if (str[0] == '+')
  356. X            dest[0] = ' ';
  357. X        else if (str[0] == '%' && ishex(str[1]) && ishex(str[2]))
  358. X        {
  359. X            dest[0] = (unsigned char) htoi(str + 1);
  360. X            str += 2;
  361. X        }
  362. X        else
  363. X            dest[0] = str[0];
  364. X
  365. X        str++;
  366. X        dest++;
  367. X    }
  368. X
  369. X    dest[0] = '\0';
  370. X}
  371. X
  372. X/*
  373. X * Print the start of an error message.
  374. X */
  375. Xstatic void
  376. Xhttp_head()
  377. X{
  378. X    puts("Content-type: text/html\n");
  379. X    puts("<html><head><title>Error!</title></head><body>");
  380. X    puts("<h1>An error has occurred while processing your request.</h1>");
  381. X}
  382. X
  383. X/*
  384. X * Print an HTML error string with the right HTTP header and exit.
  385. X */
  386. Xstatic void
  387. Xhtml_perror(str)
  388. X    char    *str;
  389. X{
  390. X    http_head();
  391. X
  392. X    puts("<p>The following error was encountered while processing");
  393. X    puts("your query.");
  394. X    puts("<blockquote>");
  395. X    printf("%s: %s\n", str, sys_errlist[errno]);
  396. X    puts("</blockquote>");
  397. X    puts("<p>Please try again later.");
  398. X    puts("</body></html>");
  399. X
  400. X    exit(1);
  401. X}
  402. X
  403. X/*
  404. X * Stuff a URL-unescaped variable, with the prefix on its name, into the
  405. X * environment.  Uses the "=" from the CGI arguments.  Putting an "=" in
  406. X * a field name is probably a bad idea.
  407. X *
  408. X * If the variable is already defined, append a '#' to it along with the
  409. X * new value.
  410. X */
  411. Xstatic void
  412. Xstuffenv(var)
  413. X    char    *var;
  414. X{
  415. X    char    *buf, *c, *oldval, *newval;
  416. X
  417. X    url_unescape(var);
  418. X
  419. X    /*
  420. X     * Allocate enough memory for the variable name and its value.
  421. X     */
  422. X    buf = malloc(strlen(var) + sizeof(PREFIX) + 1);
  423. X    if (buf == NULL)
  424. X        html_perror("stuffenv");
  425. X
  426. X    strcpy(buf, PREFIX);
  427. X    strcpy(buf + sizeof(PREFIX) - 1, var);        /* save a few cycles */
  428. X
  429. X    /*
  430. X     * If, for some reason, there wasn't an = in the query string,
  431. X     * add one so the environment will be valid.
  432. X     */
  433. X    for (c = buf; *c != '\0'; c++)
  434. X        if (*c == '=')
  435. X            break;
  436. X    if (*c == '\0')
  437. X        c[1] = '\0';
  438. X    
  439. X    /*
  440. X     * Check for the presence of the variable.
  441. X     */
  442. X    *c = '\0';
  443. X    if (oldval = getenv(buf))
  444. X    {
  445. X        newval = malloc(strlen(oldval) + strlen(buf) + strlen(c+1) + 2);
  446. X        if (newval == NULL)
  447. X            html_perror("stuffenv: append");
  448. X        
  449. X        *c = '=';
  450. X        strcpy(newval, buf);
  451. X        strcat(newval, "#");
  452. X        strcat(newval, oldval);
  453. X        free(buf);
  454. X    }
  455. X    else
  456. X    {
  457. X        *c = '=';
  458. X        newval = buf;
  459. X    }
  460. X
  461. X    putenv(newval);
  462. X}
  463. X
  464. X/*
  465. X * Scan a query string, stuffing variables into the environment.  This
  466. X * should ideally just use strtok(), but that's not available everywhere.
  467. X */
  468. Xstatic void
  469. Xscanquery(q)
  470. X    char    *q;
  471. X{
  472. X    char    *next = q;
  473. X
  474. X    do {
  475. X        while (*next && *next != '&')
  476. X            next++;
  477. X        if (! *next)
  478. X            next = NULL;
  479. X        else
  480. X            *next = '\0';
  481. X        
  482. X        stuffenv(q);
  483. X        if (next)
  484. X            *next++ = '&';
  485. X        q = next;
  486. X    } while (q != NULL);
  487. X}
  488. X
  489. X/*
  490. X * Read a POST query from standard input into a dynamic buffer.  Terminate
  491. X * it with a null character.
  492. X */
  493. Xstatic char *
  494. Xpostread()
  495. X{
  496. X    char    *buf = NULL;
  497. X    int    size = 0, sofar = 0, got;
  498. X
  499. X    buf = getenv("CONTENT_TYPE");
  500. X    if (buf == NULL || strcmp(buf, "application/x-www-form-urlencoded"))
  501. X    {
  502. X        http_head();
  503. X        puts("<p>No content type was passed to uncgi.</body></html>");
  504. X        exit(1);
  505. X    }
  506. X
  507. X    buf = getenv("CONTENT_LENGTH");
  508. X    if (buf == NULL)
  509. X    {
  510. X        http_head();
  511. X        puts("<p>The server did not tell uncgi how long the request");
  512. X        puts("was.</body></html>");
  513. X        exit(1);
  514. X    }
  515. X    
  516. X    size = atoi(buf);
  517. X    buf = malloc(size);
  518. X    if (buf == NULL)
  519. X        html_perror("postread");
  520. X    do
  521. X    {
  522. X        got = fread(buf + sofar, 1, size - sofar, stdin);
  523. X        sofar += got;
  524. X    } while (got && sofar < size);
  525. X
  526. X    buf[sofar] = '\0';
  527. X
  528. X    return (buf);
  529. X}
  530. X
  531. X/*
  532. X * Run a shell script.  We use this instead of the OS's "#!" mechanism
  533. X * because that mechanism doesn't work too well on SVR3-based systems.
  534. X */
  535. Xvoid
  536. Xrunscript(shell, script)
  537. X    char    *shell, *script;
  538. X{
  539. X    char    *argvec[4], *space;
  540. X    int    pos;
  541. X
  542. X    if (shell[0] != '/')
  543. X        return;
  544. X    
  545. X    pos = strlen(shell) - 1;
  546. X    if (shell[pos] == '\n')
  547. X        shell[pos] = '\0';
  548. X
  549. X    argvec[0] = shell;
  550. X
  551. X    /*
  552. X     * See if there's an argument string.  strchr() isn't available
  553. X     * everywhere, so do it ourselves.
  554. X     */
  555. X    for (space = shell; *space; space++)
  556. X        if (*space == ' ')
  557. X            break;
  558. X
  559. X    if (*space)
  560. X    {
  561. X        *space = '\0';
  562. X        argvec[1] = space + 1;
  563. X        argvec[2] = script;
  564. X        argvec[3] = NULL;
  565. X    }
  566. X    else
  567. X    {
  568. X        argvec[1] = script;
  569. X        argvec[2] = NULL;
  570. X    }
  571. X
  572. X    execv(shell, argvec);
  573. X    /* Fall back to main() on error. */
  574. X}
  575. X
  576. X/*
  577. X * Main program, optionally callable as a library function.
  578. X */
  579. Xvoid
  580. X#ifdef NO_MAIN
  581. Xuncgi()
  582. X#else
  583. Xmain(argc, argv)
  584. X    int    argc;
  585. X    char    **argv;
  586. X#endif
  587. X{
  588. X    char    *query, *program, *pathinfo, *newpathinfo, *method;
  589. X    char    *ptrans, *ptend;
  590. X    char    *argvec[2], shellname[200];
  591. X    int    proglen;
  592. X    FILE    *fp;
  593. X
  594. X    /*
  595. X     * First, get the query string, wherever it is, and stick its
  596. X     * component parts into the environment.  Allow combination
  597. X     * GET and POST queries, even though that's a bit strange.
  598. X     */
  599. X    query = getenv("QUERY_STRING");
  600. X    if (query != NULL && strlen(query))
  601. X        scanquery(query);
  602. X
  603. X    method = getenv("REQUEST_METHOD");
  604. X    if (method != NULL && ! strcmp(method, "POST"))
  605. X    {
  606. X        query = postread();
  607. X        if (query[0] != '\0')
  608. X            scanquery(query);
  609. X    }
  610. X
  611. X    if (query == NULL)
  612. X    {
  613. X        http_head();
  614. X        puts("<p>The 'uncgi' program couldn't find a query to");
  615. X        puts("process.\n</body></html>");
  616. X        exit(1);
  617. X    }
  618. X
  619. X#ifndef NO_MAIN
  620. X    /*
  621. X     * Now figure out which program the caller *really* wants, and adjust
  622. X     * PATH_INFO and PATH_TRANSLATED to look right to that program.
  623. X     */
  624. X    pathinfo = getenv("PATH_INFO");
  625. X    if (pathinfo != NULL && pathinfo[0])
  626. X    {
  627. X        proglen = 1;    /* path_info always starts with '/' */
  628. X
  629. X        while (pathinfo[proglen] && pathinfo[proglen] != '/')
  630. X            proglen++;
  631. X
  632. X        program = malloc(proglen + sizeof(CGI_BIN));
  633. X        if (program == NULL)
  634. X            html_perror("program");
  635. X        strcpy(program, CGI_BIN);
  636. X        strncat(program + sizeof(CGI_BIN) - 1, pathinfo, proglen);
  637. X
  638. X        /*
  639. X         * Strip "program" from PATH_TRANSLATED.
  640. X         * XXX - this depends on strcpy() copying front to back.
  641. X         */
  642. X        ptrans = getenv("PATH_TRANSLATED");
  643. X        if (ptrans != NULL)
  644. X        {
  645. X            ptend = ptrans + strlen(ptrans) - strlen(pathinfo);
  646. X            strcpy(ptend, ptend + proglen);
  647. X            ptend = malloc(strlen(ptrans) +
  648. X                    sizeof("PATH_TRANSLATED="));
  649. X            strcpy(ptend, "PATH_TRANSLATED=");
  650. X            strcat(ptend, ptrans);
  651. X            putenv(ptend);
  652. X        }
  653. X
  654. X        pathinfo += proglen;
  655. X        newpathinfo = malloc(strlen(pathinfo) + sizeof("PATH_INFO="));
  656. X        if (newpathinfo == NULL)
  657. X            html_perror("newpathinfo");
  658. X        strcpy(newpathinfo, "PATH_INFO=");
  659. X        strcat(newpathinfo, pathinfo);
  660. X        putenv(newpathinfo);
  661. X
  662. X
  663. X    }
  664. X    else
  665. X    {
  666. X        /*
  667. X         * No PATH_INFO means no program to run.
  668. X         */
  669. X        http_head();
  670. X        puts("<p>Whoever wrote this form doesn't know how to use");
  671. X        puts("the 'uncgi' program, because they didn't tell it");
  672. X        puts("what to run.");
  673. X        puts("<h5>(Bummer.)</h5></body></html>");
  674. X
  675. X        exit(0);
  676. X    }
  677. X
  678. X    /*
  679. X     * SVR3-based systems seem to have trouble running shell scripts.
  680. X     * So if that's what this is, run its shell explicitly.
  681. X     */
  682. X    fp = fopen(program, "r");
  683. X    if (fp != NULL)
  684. X    {
  685. X        if (fgets(shellname, sizeof(shellname), fp) != NULL)
  686. X        {
  687. X            fclose(fp);
  688. X            if (shellname[0] == '#' && shellname[1] == '!')
  689. X                runscript(shellname + 2, program);
  690. X        }
  691. X        fclose(fp);
  692. X    }
  693. X
  694. X    /*
  695. X     * Now execute the program.
  696. X     */
  697. X    argvec[0] = program;
  698. X    argvec[1] = NULL;
  699. X    execv(program, argvec);
  700. X
  701. X    /*
  702. X     * If we get here, the exec failed.
  703. X     */
  704. X    html_perror(program);
  705. X#endif
  706. X}
  707. END_OF_FILE
  708. if test 8558 -ne `wc -c <'uncgi.c'`; then
  709.     echo shar: \"'uncgi.c'\" unpacked with wrong size!
  710. fi
  711. # end of 'uncgi.c'
  712. fi
  713. echo shar: End of shell archive.
  714. exit 0
  715.